#pragma once
#include <iostream>
#include <cstring>
#include <poll.h>
#include <sys/types.h>
#include <string>
#include "socket.hpp"
#include "log.hpp"

namespace PollServer
{
    class Poll
    {
        static const int defaultfd = -1;
        static const int maxcap = 1024;
        static const int invalid = 0;

    public:
        Poll(uint16_t port)
            : _listenfd(new SocketInter::SockIn(port))
        {
            for(int i = 0;i < maxcap;i++)
            {
                _fd_arr[i].fd = defaultfd;
                _fd_arr[i].events = invalid;
            }

        }
        void Init()
        {
            _listenfd->InitSockaddr();
            _listenfd->Socket();
            _listenfd->Bind();
            _listenfd->Listen();
        }
        void run()
        {
            _fd_arr[0].fd = _listenfd->listenfd();
            _fd_arr[0].events = POLLIN;
            while (true)
            {
                int timeout = 0;
                int n = poll(_fd_arr, maxcap, timeout);
                switch (n)
                {
                case 0:
                    std::cout << "超时" << std::endl;
                    break;
                case -1:
                    std::cout << "select errno:" << errno << ",strerror:" << strerror(errno) << std::endl;
                    break;
                default:
                    Distribution();
                }
            }
        }

        void Distribution()
        {
            for (int i = 0; i < maxcap; i++)
            {
                int fd = _fd_arr[i].fd;
                if (fd == defaultfd)
                    continue;

                if (fd == _listenfd->listenfd())
                {
                    GetLink();
                }
                else
                {
                    EventReady(fd, i);
                }
            }
        }

        void GetLink() // 获取连接
        {
            int sock = _listenfd->Accept();
            std::cout << "获取链接成功" << std::endl;
            bool fill = true;
            for (int i = 0; i < maxcap; i++)
            {
                if (_fd_arr[i].fd == defaultfd)
                {
                    _fd_arr[i].fd = sock;
                    _fd_arr[i].events = POLLIN;
                    fill = false;
                    break;
                }
            }

            if (fill)
            {
                std::cout << "满载" << std::endl;
                close(sock);
            }

            std::string ip = _listenfd->GetClientip();
            uint16_t port = _listenfd->GetClientport();

            mylog::log(Info, "客户端ip:%s,端口号:%d", ip.c_str(), port);
        }

        void EventReady(int fd, int pos) // 事件就绪
        {
            char bufstr[1024];
            int n = read(fd, bufstr, sizeof(bufstr));
            if (n > 0)
            {
                std::cout << bufstr << std::endl;
                close(fd);
                _fd_arr[pos].fd = defaultfd;
                _fd_arr[pos].events = invalid;
            }
            else if (n == 0)
            {
                std::cout << "写端退出" << std::endl;
                exit(1);
            }
            else
            {
                if (errno == EWOULDBLOCK)
                {
                    std::cout << "暂无数据可读" << std::endl;
                }
                else
                {
                    std::cout << "读取失败" << std::endl;
                    // break;
                }
            }
        }

    private:
        SocketInter::SockIn *_listenfd;
        struct pollfd _fd_arr[maxcap];
    };
}